import {
  NVirtualList,
  type VirtualListProps,
  type VirtualListInst,
} from "naive-ui";
import type { HTMLAttributes } from "vue";
import { getSlotsDom } from "../utils";
import type { BaseComponentType } from "../types";

export type VirtualListFactoryConstructorType = {
  props?: Omit<VirtualListProps, "itemSize"> & { itemSize: number };
  attrs?: HTMLAttributes;
  defaultSlot?: (
    item: Record<string, unknown>,
    index: number | string
  ) => BaseComponentType;
};

export class VirtualListFactory {
  private props: Omit<VirtualListProps, "itemSize"> & { itemSize: number } = {
    itemSize: 50,
  };
  private attrs: HTMLAttributes = {};
  //
  private defaultSlot: (
    item: Record<string, unknown>,
    index: number | string
  ) => BaseComponentType = () => null;
  private domRef: VirtualListInst | null = null;

  constructor(data?: VirtualListFactoryConstructorType) {
    if (data?.props) this.setProps(data.props);
    if (data?.attrs) this.setAttrs(data.attrs);
    if (data?.defaultSlot) this.setDefault(data.defaultSlot);
  }

  setAttrs(attrs: HTMLAttributes) {
    this.attrs = attrs;
    return this;
  }
  setProps(props: Omit<VirtualListProps, "itemSize"> & { itemSize: number }) {
    this.props = props;
    return this;
  }

  setDefault(
    defaultSlot: (
      item: Record<string, unknown>,
      index: number | string
    ) => BaseComponentType
  ) {
    this.defaultSlot = defaultSlot;
    return this;
  }

  scrollTo(x: number, y: number) {
    this.domRef?.scrollTo(x, y);
  }

  create() {
    return (
      <NVirtualList
        ref={(el: HTMLElement) => {
          this.domRef = el as unknown as VirtualListInst;
        }}
        {...this.attrs}
        {...this.props}
      >
        {{
          default:
            this.defaultSlot({}, 0) != null
              ? (item: Record<string, unknown>, index: number) =>
                  getSlotsDom(this.defaultSlot(item, index))
              : null,
        }}
      </NVirtualList>
    );
  }
}
